/*
	Copyright (c) 2011 Andrey O. Zbitnev (azbitnev@gmail.com)
	Licensed under the MIT License (LICENSE.txt).

	$Id$

	version: 0.8pa
*/

(function ($) {

	// private vars
	var serial = 1, installed = false, contexts = []

	// class starating
	$.ys.starating = {

		create: function (selector, options) {

			var defaults = {
				value: function ($elem) { var val = $elem.data('ys-starating-value'); return (val ? parseFloat(val) : 0) },
				nstars: 5,
				ncolors: 5,
				readonly: true,
				onchange: undefined // function ($elem, value) { ... }
			}

			var opts = $.extend(defaults, options)
			var $sel = $(selector)

			if (!installed) {
				var savedVal = $.fn.val
				$.fn.val = function (value) {
					if ($(this).data('ys-starating-id')) {
						var ctx = $.ys.starating.getContext(this)
						return (value === undefined ? ctx.get() : ctx.set(value))
					}
					return savedVal.apply(this, arguments)
				}
				installed = true
			}

			$sel.each(function () {

				var ctx = { }
				for (var key in opts)
					ctx[key] = opts[key]

				var $rating = $(this)

				if (!$rating.hasClass('ys-starating'))
					$rating.addClass('ys-starating')

				var val = (typeof ctx.value == 'function' ? ctx.value($rating) : ctx.value)

				for (var i = 0; i < ctx.nstars; i ++) {
					var $star = $('<div class="star"/>').data('index', i + 1)
					$star.mouseover(function (evt) {
						if (ctx.readonly)
							return;
						$.ys.starating.getContext($rating).set(parseInt($(this).data('index')), true)
					}).click(function (evt) {
						if (ctx.readonly)
							return;
						var v = parseInt($(this).data('index'))
						$.ys.starating.getContext($rating).set(v)
					})
					$rating.append($star)
					ctx.width = $star.outerWidth()
					ctx.height = $star.outerHeight()
				}
				$rating.append($('<div class="clear"/>'))
					.css({
						width: '' + (ctx.width * ctx.nstars) + 'px',
						height: '' + ctx.height + 'px'
					})

				var id = serial ++
				$(this).data('ys-starating-id', id)
				contexts[id] = ctx

				$.ys.starating.getContext(this).attr('readonly', ctx.readonly).set(val, true)
			})
		},

		getContext: function (selector) {
			var $sel = $(selector)
			return {
				set: function (val, dontRaiseEvent) {

					$sel.data('ys-starating-value', val)

					var intVal = parseInt(val)
					var fract = parseInt(val.toFixed(1).replace(/^.*\.(\d+)$/, '$1'))

					$sel.each(function () {

						var $rating = $(this)
						var opts = contexts[$rating.data('ys-starating-id')]

						var x = -parseInt((val / (opts.nstars + 0.1)) * opts.ncolors) * opts.width

						$rating.find('.star').each(function (i) {
							
							var $star = $(this)
							var y = 0

							if (i < intVal) {
								y = -(opts.height * 10)
							} else if (i == intVal) {
								y = -(opts.height * fract)
							}

							$star.css({ 'background-position': '' + x + 'px ' + y + 'px' })
						})
						if (!dontRaiseEvent && opts.onchange)
							opts.onchange($rating, val)
					})
					return this
				},
				get: function () {
					return $sel.data('ys-starating-value')
				},
				attr: function (key, val) {
					var opts = contexts[$sel.data('ys-starating-id')]
					if (val === undefined) {
						return opts[key]
					} else {
						opts[key] = val
						if (key == 'readonly') {
							$sel.children('.star').css({ cursor: (!val ? 'pointer' : 'auto') })
						}
						return this
					}
				}
			}
		}
	}

})(jQuery);

